package com.tcoiss.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcoiss.app.service.IElectronicFenceService;
import com.tcoiss.app.service.IFenceDistrictService;
import com.tcoiss.app.service.IFencePointsService;
import com.tcoiss.app.service.ITrackServiceService;
import com.tcoiss.common.core.domain.R;
import com.tcoiss.common.core.enums.ErroEnums;
import com.tcoiss.common.core.exception.CustomException;
import com.tcoiss.common.core.utils.SecurityUtils;
import com.tcoiss.common.core.utils.StringUtils;
import com.tcoiss.common.core.web.domain.AjaxResult;
import com.tcoiss.common.component.service.ApiHelperService;
import com.tcoiss.system.api.RemoteUserService;
import com.tcoiss.system.api.model.LoginUser;
import com.tcoiss.app.domain.ElectronicFence;
import com.tcoiss.app.domain.FenceDistrict;
import com.tcoiss.app.mapper.FenceDistrictMapper;
import com.tcoiss.app.utils.SplitList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FenceDistrictServiceImpl extends ServiceImpl<FenceDistrictMapper, FenceDistrict> implements IFenceDistrictService {

    @Autowired
    private IFenceDistrictService iFenceDistrictService;

    @Autowired
    private ITrackServiceService iTrackServiceService;

    @Resource
    private IFencePointsService iFencePointsService;

    @Autowired
    private ApiHelperService apiHelperService;

    @Resource
    private RemoteUserService remoteUserService;

    @Resource
    private IElectronicFenceService iElectronicFenceService;


    @Override
    public List<FenceDistrict> queryList(FenceDistrict fenceDistrict) {
        LambdaQueryWrapper<FenceDistrict> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(fenceDistrict.getAdcode())) {
            lqw.eq(FenceDistrict::getAdcode, fenceDistrict.getAdcode());
        }
        if(fenceDistrict.getParentId() != null){
            lqw.eq(FenceDistrict::getParentId, fenceDistrict.getParentId());
        }
        if (StringUtils.isNotBlank(fenceDistrict.getCity())) {
            lqw.eq(FenceDistrict::getCity, fenceDistrict.getCity());
        }
        if (StringUtils.isNotBlank(fenceDistrict.getCityCode())) {
            lqw.eq(FenceDistrict::getCityCode, fenceDistrict.getCityCode());
        }
        if (StringUtils.isNotBlank(fenceDistrict.getDistrictName())) {
            lqw.eq(FenceDistrict::getDistrictName, fenceDistrict.getDistrictName());
        }
        if (fenceDistrict.getDistrictLevel() != null) {
            lqw.eq(FenceDistrict::getDistrictLevel, fenceDistrict.getDistrictLevel());
        }
        if(fenceDistrict.getDistrictPop() == null){
            lqw.in(FenceDistrict::getDistrictPop, getTowsPopByRole());
        }else {
            lqw.eq(FenceDistrict::getDistrictPop, fenceDistrict.getDistrictPop());
        }
        List<FenceDistrict> fd = this.list(lqw);
        return fd;
    }


    /**
     * 保存区域
     */
    @Override
    public boolean saveDistricts(List<FenceDistrict> districts) {
        int max = districts.size();
        for (int i = 0; i < max; i++) {
            FenceDistrict fenceDistrict = districts.get(i);
            String districtName = fenceDistrict.getCity() + "-" + fenceDistrict.getAdcodeName();
            if (max > 1) {
                districtName = districtName + i;
            }
            fenceDistrict.setDistrictName(districtName);
            fenceDistrict.setDistrictPop(0);
            if (checkDistrict(fenceDistrict)) {
                throw new CustomException(ErroEnums.DATAERRO.getCode(), new String[]{}, ErroEnums.DATAERRO.getInfo() + "区域名称重复,已存在该区域");
            }
            FenceDistrict fd = new FenceDistrict();
            fd.setDistrictName(districts.get(i).getDistrictName());
            fd.setCity(districts.get(i).getCity());
            fd.setCityCode(districts.get(i).getCityCode());
            fd.setAdcodeName(districts.get(i).getAdcodeName());
            fd.setAdcode(districts.get(i).getAdcode());
            fd.setDistrictPoints(districts.get(i).getDistrictPoints());
            fd.setYDistrictPoints(districts.get(i).getYDistrictPoints());
            fd.setDistrictLevel(districts.get(i).getDistrictLevel());
            fd.setCreateTime(districts.get(i).getCreateTime());
            fd.setDistrictColor(districts.get(i).getDistrictColor());
            fd.setDistrictPop(1);
            districts.add(fd);
        }
        return iFenceDistrictService.saveBatch(districts);
    }

    @Override
    public List<Integer> getTowsPopByRole(){
        List<Integer> towsPops = new ArrayList<>();
        R<LoginUser> user =  remoteUserService.getUserInfo(SecurityUtils.getUsername());
        HashSet<String> userRoles = (HashSet) user.getData().getRoles();
        for(String role: userRoles){
            if(role.equals("fencePs")){
                towsPops.add(0);
            }else if(role.equals("fenceAz")){
                towsPops.add(1);
            }else if(role.equals("admin")){
                towsPops.add(0);
                towsPops.add(1);
            }
        }
        return towsPops;
    }

    @Override
    public boolean copyTownOrDistrict(FenceDistrict districts) {
        if(districts.getParentId() != null){
            return copyTown(districts,1);
        }else {
            return copyDistrict(districts);
        }

    }

    @Override
    public boolean checkIsCopy(FenceDistrict districts) {
        Map<String,Object> map = new HashMap<>();
        map.put("district_id", districts.getId());
        List<ElectronicFence> efList = iElectronicFenceService.listByMap(map);
        for (ElectronicFence ef : efList){
            if(ef.getIsCopy() == 1){
                throw new CustomException(ErroEnums.DATAERRO.getCode(), new String[]{}, ErroEnums.DATAERRO.getInfo() + "该区域已被复制");
            }
        }
        return true;
    }

    private boolean copyDistrict(FenceDistrict districts){
        Map<String,Object> map = new HashMap<>();
        map.put("parent_id", districts.getId());
        List<FenceDistrict> fdList = this.listByMap(map);
        LambdaQueryWrapper<FenceDistrict> lqw = Wrappers.lambdaQuery();
        lqw.eq(FenceDistrict::getDistrictName, districts.getDistrictName());
        lqw.eq(FenceDistrict::getAdcode, districts.getAdcode());
        lqw.eq(FenceDistrict::getDistrictPop, 1);
        FenceDistrict fence = this.getOne(lqw);
        if(queryList(new FenceDistrict().setParentId(fence.getId())).size() > 0 ){
            throw new CustomException(ErroEnums.BUSERRO.getCode(), new String[]{},
                    ErroEnums.BUSERRO.getInfo() + "复制乡镇失败:" + fence.getDistrictName() + "下有拥有乡镇!!");
        }
        for (FenceDistrict fd : fdList){
            if(!copyTown(fd,0)){
                throw new CustomException(ErroEnums.BUSERRO.getCode(), new String[]{},
                        ErroEnums.BUSERRO.getInfo() + "复制乡镇失败:" + fd);
            }
        }
        return true;
    }

    /**
     * 根据配送类型乡镇查询其父区县再查询与之对应的安装区县
     * 查询安装区县下是否已有乡镇,如已有return ApiException
     * 再查询乡镇下的电子围栏,将查询出的电子围栏重新赋值
     * 设置成即安装又配送的围栏,并更新至高德上.再将本地IsCopy设置成1.
     * 再将安装区县的district_points,同步成配送的district_points.
     * 再新建一个新的乡镇,再重新赋值.
     * @param districts(前端返回的配送围栏对象) modes:0复制区县、1复制乡镇
     */
    private boolean copyTown(FenceDistrict districts,Integer modes){
        // 查询复制的配送父区县
        FenceDistrict parent = this.getById(districts.getParentId());
        // 查询与配送相同区县区域
        LambdaQueryWrapper<FenceDistrict> lqw = Wrappers.lambdaQuery();
        lqw.eq(FenceDistrict::getDistrictName, parent.getDistrictName());
        lqw.eq(FenceDistrict::getAdcode, parent.getAdcode());
        lqw.eq(FenceDistrict::getDistrictPop, 1);
        FenceDistrict fd = this.getOne(lqw);
        // 查询安装类型区县下是否有乡镇区域
        if(queryList(new FenceDistrict().setParentId(fd.getId())).size() > 0 ){
            if(modes == 1){
                throw new CustomException(ErroEnums.BUSERRO.getCode(),
                        new String[]{}, ErroEnums.BUSERRO.getInfo() + "复制乡镇失败:" + fd.getDistrictName() + "下有拥有乡镇!!");
            }
        }
        // 查询乡镇下的电子围栏
        Map<String,Object> map = new HashMap<>();
        map.put("district_id", districts.getId());
        List<ElectronicFence> efList = iElectronicFenceService.listByMap(map);
        // 给围栏属性重新赋值
        for ( ElectronicFence ef : efList ){
            ef.setFencePop("0,1");
            ef.setIsCopy(1);
            iFencePointsService.copyElectronicFence(ef);
        }
        // 给复制的区县区域的重新赋值
        fd.setDistrictPoints(parent.getDistrictPoints());
        // 给复制的乡镇围栏重新赋值
        districts.setDistrictPop(fd.getDistrictPop());
        districts.setParentId(fd.getId());
        districts.setId(null).setCreateTime(null);
        if (iFenceDistrictService.updateById(fd)) {
            if(this.save(districts)){
                return true;
            }
        }
        return false;
    }



    /**
     * 保存or修改拆分围栏
     */
    @Override
    public AjaxResult saveOrUpDataQyCache(FenceDistrict district) {
        Map<String,Object> result = new HashMap<>();
        if (district.getId() != null) {
            if(iFencePointsService.removeByDistrictId(district.getId())){
                result.put("code",200);
                result.put("message","成功");
                int num = iFenceDistrictService.updateById(district) ? 1 : 0;
                result.put("num",num);
                return AjaxResult.success(result);
            }
        } else {
            List newDistrictPaths;
            try {
                newDistrictPaths = SplitList.naiveSplitSame(district.getDistrictPointList(),district.getPointList());
                // 新增
                FenceDistrict fd = iFenceDistrictService.getById(district.getParentId());
                if(!checkDistrict(district)){
                    district.setDistrictName(district.getDistrictName());
                    district.setAdcodeName(fd.getAdcodeName());
                    district.setAdcode(fd.getAdcode());
                    district.setDistrictColor(fd.getDistrictColor());
                    district.setCity(fd.getCity());
                    district.setDistrictLevel(3);
                    //更新区域坐标
                    if(newDistrictPaths == null){
                        fd.setDistrictPoints("");
                    }else{
                        fd.setDistrictPoints(SplitList.getPointsByList(newDistrictPaths));
                    }
                    if(iFenceDistrictService.updateById(fd)){
                        result.put("code",200);
                        result.put("message","成功");
                        int num = iFenceDistrictService.save(district) ? 1 : 0;
                        result.put("num",num);
                        return AjaxResult.success(result);
                    }
                }
                result.put("code",500);
                result.put("message","名称重复请重新命名");
                return AjaxResult.success(result);
            }catch (Exception e){
                result.put("code",500);
                result.put("message",e.toString());
                return AjaxResult.success(result);
            }
        }
        throw new CustomException(ErroEnums.SYSERRO.getCode(), new String[]{district.toString()}, ErroEnums.SYSERRO.getInfo() + "数据未知错误");
    }

    @Override
    public boolean delDistrict(FenceDistrict district) {
        if(district.getDistrictLevel() == 2){
            // 删除区县和乡镇
            Map<String,Object> map = new HashMap<>();
            map.put("parent_id",district.getId());
            List<FenceDistrict> fdList = this.listByMap(map);
            List<Long> ids = fdList.stream().map(FenceDistrict::getId).collect(Collectors.toList());
            if(removeById(district.getId())){
                return this.removeByIds(ids);
            }else {
                throw new CustomException(ErroEnums.DATAERRO.getCode(), new Object[]{district.getId()},
                        ErroEnums.DATAERRO.getInfo() + "删除失败");
            }
        }else if(district.getDistrictLevel() == 3){
            // 删除乡镇
            return removeById(district.getId());
        }
        throw new CustomException(ErroEnums.DATAERRO.getCode(), new Object[]{},
                ErroEnums.DATAERRO.getInfo() + "未知围栏级别"+district.getDistrictLevel());
    }

    /** 重置区县围栏 */
    @Override
    public boolean resetDistrict(FenceDistrict district) {
        district.setDistrictPoints(district.getYDistrictPoints());
        Map<String,Object> map = new HashMap<>();
        map.put("parent_id",district.getId());
        List<FenceDistrict> fdList = this.listByMap(map);
        if(fdList.size() > 0){
            for (FenceDistrict fd : fdList){
                // 删除乡镇下的围栏
                if(resetTownDistrict(fd)){
                    removeById(fd.getId());
                }
            }
        }
        return iFenceDistrictService.updateById(district);
    }

    /** 重置乡镇围栏 */
    @Override
    public boolean resetTownDistrict(FenceDistrict district) {
        district.setDistrictPoints(district.getYDistrictPoints());
        // 删除该区域下的所有子围栏
        if (iFencePointsService.removeByDistrictId(district.getId())) {
            return iFenceDistrictService.updateById(district);
        }
        return false;
    }

    @Override
    public boolean checkDistrict(FenceDistrict district) {
        LambdaQueryWrapper<FenceDistrict> lqw = Wrappers.lambdaQuery();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(district.getDistrictName())) {
            lqw.eq(FenceDistrict::getDistrictName, district.getDistrictName());
        }
        if(district.getDistrictPop() == null){
            lqw.in(FenceDistrict::getDistrictPop, getTowsPopByRole());
        }else {
            lqw.eq(FenceDistrict::getDistrictPop,district.getDistrictPop());
        }
        if(district.getDistrictLevel() != null){
            lqw.eq(FenceDistrict::getDistrictLevel, district.getDistrictLevel());
        }
        List<FenceDistrict> list = this.list(lqw);
        if (list != null && list.size() > 0) {
            return true;
        }
        return false;
    }

    @Override
    public List<Map<String, Object>> getDistrictInfo(FenceDistrict fence, String apiCode) {
        Map<String, Object> requestMap = new HashMap<>();
        requestMap.put("keywords", fence.getCityCode());
        requestMap.put("subdistrict", 1);
        requestMap.put("extensions", "base");
        requestMap.put("key", iTrackServiceService.getDefaultKey().getGaodeKey());
        Map resultMap = apiHelperService.executeApi(apiCode, requestMap);
        if (resultMap == null) {
            throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{apiCode},
                    ErroEnums.APIERRO.getInfo() + "http请求连接异常");
        } else {
            if (Integer.valueOf(resultMap.get("infocode").toString()) == 10000) {//创建成功
                //更新坐标数据
                List<Object> citys = (List<Object>) resultMap.get("districts");
                Map<String, Object> city = (Map<String, Object>) citys.get(0);
                List<Map<String, Object>> districts = (List<Map<String, Object>>) city.get("districts");
                return districts;
            } else {
                throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{apiCode, resultMap.get("infocode").toString()},
                        ErroEnums.APIERRO.getInfo() + "接口调用异常：" + resultMap.get("info").toString());
            }
        }

    }
}
